package com.yanqu.road.server.gameplayer.module.passRoad;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.config.passroad.*;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.enums.activity.eNewServerWelfareActivityType;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.entity.player.UserPassRoad;
import com.yanqu.road.logic.bussiness.player.UserPassRoadBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.pb.PassRoadPb;
import com.yanqu.road.pb.pass.RoadProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.BagModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.PlayerModule;
import com.yanqu.road.server.gameplayer.module.xiaomian.XiaoMianModule;
import com.yanqu.road.server.logic.mail.MailManager;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.DataAnalyticsMgr;
import com.yanqu.road.server.manger.MultipleLanguageMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.activity.newserverwelfare.NewServerWelfareMgr;
import com.yanqu.road.server.manger.config.*;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 玩家关卡（新）模块
 */
public class PassRoadModule extends GeneralModule {

	private UserPassRoad userPassRoad;

	//用户屯的事件背包 passId sectionId eventId
	private Map<Integer,Map<Integer,UserPassRoadEvent>> eventBagMap;


	public PassRoadModule(GamePlayer player) {
		super(player);
	}

	private BackEndPassRecord backEndPassRecord = new BackEndPassRecord();

	private long lastReqTime;

	private long reqTimes;

	@Override
	public boolean loadData() {
		userPassRoad = UserPassRoadBussiness.getUserPassRoad(player.getUserId());
		checkSessionId(userPassRoad);
		return true;
	}

	public void checkSessionId(UserPassRoad userPassRoad) {
		if(userPassRoad == null){
			return;
		}
		if(userPassRoad.getSessionId() > 0){
			return;
		}
		PassRoadPointInfo passRoadPointInfo = PassRoadMgr.getPassRoadPointInfo(userPassRoad.getPassId(), userPassRoad.getPassProgress());
		if(passRoadPointInfo != null) {
			userPassRoad.setSessionId(passRoadPointInfo.getSessionId() + 1);
		}
	}

	@Override
	public boolean afterLoadData() {
		if(SystemOpenMgr.systemOpen(player, eSystemId.Pass.getValue())){
			initPassRoad();
			initEventBag();
		}
		return true;
	}

	@Override
	public void loginSendMsg() {
		player.notifyListener(eGamePlayerEventType.PassThroughRank.getValue(), userPassRoad);
		player.notifyListener(eGamePlayerEventType.NewServerWelfareMission.getValue(),userPassRoad);		//4.8.1同步一下关卡进度
		if(SystemOpenMgr.systemOpen(player, eSystemId.Pass.getValue())){
			//发放邮件
			if(!userPassRoad.isEventUpdate()){
				//更新新关卡事件留下的，要一直保留
				userPassRoad.setEventUpdate(true);
				player.getModule(PassTransportModule.class).addVersionUpdateTransport();
//				versionUpdateEventAdd();
			}
		}
		syncUserPassRoad();
	}

	@Override
	public boolean saveData() {
		if (null != userPassRoad) {
			if (userPassRoad.isInsertOption()) {
				UserPassRoadBussiness.addUserPassRoad(userPassRoad);
			}else if (userPassRoad.isUpdateOption()) {
				UserPassRoadBussiness.updateUserPassRoad(userPassRoad);
			}
		}
		return true;
	}

	public void initPassRoadSystem(){
		//已经解锁了才需要
		initPassRoad();
		initEventBag();
		syncUserPassRoad();
	}

	private void syncUserPassRoad(){
		if(userPassRoad != null){
			RoadProto.RoadConfigMsg.Builder configMsg = RoadProto.RoadConfigMsg.newBuilder();
			//没有配置了
			if(userPassRoad.getPassId() <= PassRoadMgr.getLastPassRoadInfo().getId()){
				List<PassRoadPointInfo> pointList = PassRoadMgr.getPassRoadPointList(userPassRoad.getPassId());
				PassRoadInfo passRoadInfo = PassRoadMgr.getPassRoadInfo(userPassRoad.getPassId());
				List<Integer> sliverCostParamList = PassRoadMgr.getCostMinMaxParam(passRoadInfo.getId());
				configMsg = PassRoadPb.parsePassRoadConfigMsg(pointList,passRoadInfo,sliverCostParamList);
			}
			player.sendPacket(Protocol.U_PASS_ROAD_CONFIG, configMsg);
			RoadProto.RoadTempMsg.Builder userMsg = PassRoadPb.parsePassRoadTempMsg(userPassRoad);
			userMsg.setMaxPassId(PassRoadMgr.getLastPassRoadInfo().getId());
			userMsg.setTransportId(userPassRoad.getTransportId());
			player.sendPacket(Protocol.U_PASS_ROAD_INFO, userMsg);
		}
	}

	public void initEventBag(){
		eventBagMap = JSON.parseObject(userPassRoad.getEventData(),new TypeReference<Map<Integer, Map<Integer, UserPassRoadEvent>>>(){});
		List<UserPassRoadEvent>  userPassRoadEvents = new ArrayList<>();
		for (int passId : eventBagMap.keySet()){
			Map<Integer,UserPassRoadEvent> eventSectionMap = eventBagMap.get(passId);
			for (int sectionId : eventSectionMap.keySet()){
				UserPassRoadEvent eventData = eventSectionMap.get(sectionId);
				UserPassRoadEvent userEvent = new UserPassRoadEvent();
				userEvent.setPassId(eventData.getPassId());
				userEvent.setSectionId(eventData.getSectionId());
				userEvent.setEventId(eventData.getEventId());
				userEvent.setSessionId(eventData.getSessionId());
				userEvent.setSessionSectionId(eventData.getSessionSectionId());
				userEvent.setCreateTime(eventData.getCreateTime());
				userPassRoadEvents.add(userEvent);
			}
		}
		userPassRoad.setUserPassRoadEvents(userPassRoadEvents);
	}

	//版本更新后把玩家之前的事件全部怼上去
	private void versionUpdateEventAdd(){
		Property eventAddReward = PassRoadMgr.getVersionUpdateEventAddReward(userPassRoad);
		if(eventAddReward != null){
			UserInfo userInfo = player.getUserInfo();
			String title = MultipleLanguageMgr.getContent(MailManager.PASS_EVENT_RECALL_TITLE, userInfo.getLanguage());
			String content = MultipleLanguageMgr.getContent(MailManager.PASS_EVENT_RECALL_CONTENT, userInfo.getLanguage());
			MailManager.sendMail(userInfo.getUserId(), eMailType.SYSTEM.getValue(), PropertyHelper.parsePropertyToString(eventAddReward), content, title);
			log.error("发送老用户关卡事件返利邮件成功，userId: {}，昵称: {}，vip : {},奖励：{}",
					userInfo.getUserId(), userInfo.getNickName(), userInfo.getVipExp(), PropertyHelper.parsePropertyToString(eventAddReward));
		}
//        putEventBagVersion(eventAddMap);
		/*for(Integer passId : eventAddMap.keySet()){
			for(Integer sessionId : eventAddMap.get(passId).keySet()){
				PassRoadPointInfo passRoadPointInfo = PassRoadMgr.getPassRoadPointInfo(passId,sessionId);
				if(passRoadPointInfo != null){
					putEventBag(passRoadPointInfo);
				}
			}
		}*/
	}

	private void initPassRoad() {
		if (null == userPassRoad) {
			UserPassRoad temp = new UserPassRoad();
			temp.setUserId(player.getUserId());
			temp.setPassId(PassRoadMgr.getFirstPassRoadInfo().getId());
			temp.setPassProgress(0);
			temp.setSessionId(1);
			temp.setModifyTime(System.currentTimeMillis() / 1000);
			temp.setTransportId(0);
			temp.setEventUpdate(true);
			temp.setInsertOption();
			userPassRoad = temp;
		}
	}

	public UserPassRoad getUserPassRoad() {
		return userPassRoad;
	}

	public int getUserPassId() {
		if (null == userPassRoad) {
			return 0;
		}
		return userPassRoad.getPassId();
	}

	public PassRoadPointInfo getPassPointInfo(){
		PassRoadPointInfo passPointInfo = PassRoadMgr.getPassRoadPointInfo(userPassRoad.getPassId(),userPassRoad.getPassProgress());
		if(passPointInfo == null){
			return PassRoadMgr.getLastPassRoadPointInfo();
		}
		return passPointInfo;
	}

	/**
	 * 关卡战斗
	 */
	public int battle(boolean isEventSelect, int selectId, List<Integer> patronIdList, List<Integer> beautyIdList, boolean isBackEnd, int maxSilverBuffTimes, int maxItemBuffTimes,int autoBuffOption) {
		long nowTime = System.currentTimeMillis();
		if (nowTime - lastReqTime > DateHelper.SECOND_MILLIONS) {
			lastReqTime = nowTime;
			reqTimes = 1;
		} else {
			reqTimes++;
		}
		userPassRoad.setMaxRequestTimesOneSecond(reqTimes);
		if (null == userPassRoad) {
			return GameErrorCode.E_SYSTEM_NO_OPEN;
		}
		PassRoadInfo passInfo = PassRoadMgr.getPassRoadInfo(userPassRoad.getPassId());
		PassRoadPointInfo passPointInfo = PassRoadMgr.getPassRoadPointInfo(userPassRoad.getPassId(), userPassRoad.getPassProgress());
		if (null == passInfo || passPointInfo == null) {
			return GameErrorCode.E_PASS_MAX;
		}
		if (!isEventSelect && !canPutEventBag()) {
			return GameErrorCode.E_PASS_ROAD_EVENT_MAX;
		}
		if (isBackEnd && !backEndPassRecord.isHadBackend()) {
			backEndPassRecord.setHadBackend(true);
			backEndPassRecord.setStartPassId(userPassRoad.getPassId());
			PassRoadPointInfo pointInfo = PassRoadMgr.getPassRoadPointInfo(userPassRoad.getPassId(), userPassRoad.getPassProgress());
			if (pointInfo != null) {
				backEndPassRecord.setStartSessionId(pointInfo.getSessionId());
			} else {
				log.error("set BackEndPassRecord.startSessionId error! PassRoadMgr.getPassRoadPointInfo(passId = {}, passProgress = {})", userPassRoad.getPassId(), userPassRoad.getPassProgress());
			}
		}
		int res = 0;
		if (passPointInfo.isBoss()) {//boss关
			res = battleBoss(passInfo, isBackEnd, maxSilverBuffTimes, maxItemBuffTimes,autoBuffOption);
		} else {//普通关
			res = battleNormal(isBackEnd);
		}
		if (res != 0) {
			return res;
		}

		//处理事件
		if (passPointInfo.isSessionEnd() && passPointInfo.getEventId() != 0) {
			if (isEventSelect) {
				if (passPointInfo.getEventId() != 0) {
					PassRoadEventInfo eventInfo = passPointInfo.getEvent();
					PassRoadMgr.passEvent(player, eventInfo, selectId, patronIdList, beautyIdList);
				}
			} else {
				putEventBag(passPointInfo);
				if (isBackEnd) {
					backEndPassRecord.setEventNum(backEndPassRecord.getEventNum() + 1);
				}
			}
		}
		return 0;
	}

	public boolean canPutEventBag(){
		int titleId = player.getUserInfo().getTitleId();
		int allEventNum = 0;
		for(Map<Integer,UserPassRoadEvent> eventList : eventBagMap.values()){
			allEventNum += eventList.size();
		}
		int num = ConfigMgr.getPassRoadEventNum(titleId);
		num += CurioMgr.getSkillAdditionBySkillType(eSkillType.PassEventNumSkill.getValue(), player, 0);
		return num > allEventNum;
	}

	private void putEventBag(PassRoadPointInfo info){
		if(info.getEventId() == 0){
			return;
		}
		if(!eventBagMap.containsKey(info.getId())){
			eventBagMap.put(info.getId(),new ConcurrentHashMap<>());
		}
		UserPassRoadEvent userEvent = new UserPassRoadEvent();
		userEvent.setPassId(info.getId());
		userEvent.setSectionId(info.getSectionId());
		userEvent.setEventId(info.getEventId());
		userEvent.setSessionId(info.getSessionId());
		userEvent.setSessionSectionId(info.getSessionSectionId());
		userEvent.setCreateTime(System.currentTimeMillis());

		eventBagMap.get(info.getId()).put(info.getSectionId(),userEvent);
		userPassRoad.addUserPassRoadEvent(userEvent);
		userPassRoad.setEventData(JSON.toJSONString(eventBagMap));
	}

	//版本更新把用户以前的事件一次发给玩家
	private void putEventBagVersion(Map<Integer,Map<Integer,Integer>> eventAddMap){
        for(Integer passId : eventAddMap.keySet()){
            for(Integer sessionId : eventAddMap.get(passId).keySet()){
                PassRoadPointInfo info = PassRoadMgr.getPassRoadPointInfo(passId,sessionId);
                UserPassRoadEvent userEvent = new UserPassRoadEvent();
                userEvent.setPassId(info.getId());
                userEvent.setSectionId(info.getSectionId());
                userEvent.setEventId(info.getEventId());
                userEvent.setSessionId(info.getSessionId());
                userEvent.setSessionSectionId(info.getSessionSectionId());
                userEvent.setCreateTime(System.currentTimeMillis());
				if(!eventBagMap.containsKey(info.getId())){
					eventBagMap.put(info.getId(),new ConcurrentHashMap<>());
				}
                eventBagMap.get(info.getId()).put(info.getSectionId(),userEvent);
                userPassRoad.addUserPassRoadEvent(userEvent);
            }
        }
		userPassRoad.setEventData(JSON.toJSONString(eventBagMap));
	}

	/**
	 * 鼓舞
	 */
	public int buyBuff(int type, int buyTimes){
		if(null == userPassRoad){
			return GameErrorCode.E_SYSTEM_NO_OPEN;
		}
		PassRoadInfo passInfo = PassRoadMgr.getPassRoadInfo(userPassRoad.getPassId());
		PassRoadPointInfo passPointInfo = PassRoadMgr.getPassRoadPointInfo(userPassRoad.getPassId(),userPassRoad.getPassProgress());

		if(null == passInfo || passPointInfo == null){
			return GameErrorCode.E_PASS_MAX;
		}
		if(!passPointInfo.isBoss()){
			return GameErrorCode.E_PASS_CAN_NO_BUY_BUFF;
		}
		if(passPointInfo.getId() < GameConfig.PASS_SILVER_BUFF_MIN_LEVEL){
			return GameErrorCode.E_PASS_CAN_NO_BUY_BUFF;
		}
		if(1 == type){
			return silverBuyBuff(new BigInteger(passInfo.getBaseInspireConsume()), buyTimes);
		}else if(2 == type){
			return itemBuyBuff(buyTimes);
		}else {
			return GameErrorCode.E_PASS_BUY_BUFF_TYPE_ERROR;
		}
	}

	/**
	 * 银两鼓舞
	 */
	private int silverBuyBuff(BigInteger baseCost, int buyTimes){
		for(int i = 0; i < buyTimes; i++){
			if(userPassRoad.getBuyBuffTimes() >= ConfigMgr.getMaxPassSilverBuyBuffTimes()){
				return GameErrorCode.E_PASS_SILVER_BUY_BUFF_MAX;
			}
			BigInteger silver = PassRoadMgr.getSilverBuyBuffCost(player, baseCost, userPassRoad.getBuyBuffTimes());
			//消耗银两
			if(!player.getModule(CurrencyModule.class).removeCurrency(new Property(GameConfig.GAME_MONEY_SILVER, silver),
					eLogMoneyType.Pass, eLogMoneyType.PassSilverBuyBuff)){
				if(0 == i){
					return GameErrorCode.E_BAG_SILVER_NO_ENOUGH;
				}else {
					break;
				}
			}
			//鼓舞次数增加
			userPassRoad.setBuyBuffTimes(userPassRoad.getBuyBuffTimes() + 1);
		}
		return 0;
	}

	/**
	 * 道具鼓舞
	 */
	private int itemBuyBuff(int buyTimes){
		for(int i = 0; i < buyTimes; i++){
			if(userPassRoad.getItemBuyBuffTimes() >= GameConfig.PASS_ITEM_BUY_BUFF_MAX_TIMES){
				return GameErrorCode.E_PASS_ITEM_BUY_BUFF_MAX;
			}
			//消耗道具
			if(!player.getModule(CurrencyModule.class).removeCurrency(new Property(GameConfig.GAME_ITEM_BUY_PASS_BUFF, BigInteger.ONE),
					eLogMoneyType.Pass, eLogMoneyType.PassItemBuyBuff)){
				if(0 == i){
					return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
				}else {
					break;
				}
			}
			//鼓舞次数增加
			userPassRoad.setItemBuyBuffTimes(userPassRoad.getItemBuyBuffTimes() + 1);
		}
		return 0;
	}

	/**
	 * 普通战斗
	 */
	private int battleNormal(boolean isBackend) {
		PassRoadPointInfo passRoadPointInfo = PassRoadMgr.getPassRoadPointInfo(userPassRoad.getPassId(), userPassRoad.getPassProgress());

		BigInteger costSilver = PassRoadMgr.getPassRoadCostSilver121(player, passRoadPointInfo, userPassRoad);
		BigInteger mySilver = player.getModule(PlayerModule.class).getUserInfo().getSilver();
		if (mySilver.compareTo(costSilver) > 0) {//打得过
			//消耗银两
			player.getModule(CurrencyModule.class).removeCurrency(new Property(GameConfig.GAME_MONEY_SILVER, costSilver),
					eLogMoneyType.Pass, eLogMoneyType.PassCost);
			//更新关卡信息
			Property reward = new Property(passRoadPointInfo.getReward());
			//关卡小进度加1
			userPassRoad.setPassProgress(userPassRoad.getPassProgress() + 1);
			//更新成配置
			userPassRoad.setSessionId(passRoadPointInfo.getSessionId() + 1);
			userPassRoad.setModifyTime(System.currentTimeMillis() / 1000);

			if(passRoadPointInfo.isSessionEnd()){//进入下个关卡
				player.notifyListener(eGamePlayerEventType.PassBattle.getValue(), userPassRoad);
				player.getModule(PlayerModule.class).checkSystemOpen();
			}
			notifyPassThrough(userPassRoad);

			//获取奖励中的阅历值，马车会增加获得量
			reward = getTransportAdd(reward);
			// 奖励
			player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.Pass, eLogMoneyType.PassReward);
			player.notifyListener(eGamePlayerEventType.PassBattleSuccessTimes.getValue(), 1);
			//平台数据加一下
			player.getModule(XiaoMianModule.class).addPassRoadBossBattleTimes(1);
			if (isBackend) {
				backEndPassRecord.getNormalReward().addProperty(reward);
				backEndPassRecord.getCost().addProperty(new Property(GameConfig.GAME_MONEY_SILVER, costSilver));
			}
			DataAnalyticsMgr.trackPassRoadBattle(player, true, reward, userPassRoad, 0, 0, false);
		} else {
			DataAnalyticsMgr.trackPassRoadBattle(player, false, new Property(), userPassRoad, 0, 0, false);
			return GameErrorCode.E_PASS_ROAD_SILVER_NO_ENOUGH;
		}
		return 0;
	}

	/**
	 *boss战斗
	 */
	private int battleBoss(PassRoadInfo passRoadInfo, boolean isBackend, int maxSilverBuffTimes, int maxItemBuffTimes,int autoBuffOption) {
		PassRoadPointInfo passPointInfo = PassRoadMgr.getPassRoadPointInfo(userPassRoad.getPassId(), userPassRoad.getPassProgress());
		BigInteger enemyAbility = passPointInfo.getAbility();
		BigInteger myAbility = PatronsMgr.getPatronsTotalAbility(player.getUserId());
		if (isBackend) {
			autoBuyBuff(passRoadInfo, maxSilverBuffTimes, maxItemBuffTimes,autoBuffOption);
		}
		double addition = 0;
		if(userPassRoad.getBuyBuffTimes() > 0){
			addition += GameConfig.PASS_SILVER_BUFF_ADDITION * userPassRoad.getBuyBuffTimes();
		}
		if(userPassRoad.getItemBuyBuffTimes() > 0){
			GoodsInfo goodsInfo = GoodsMgr.getGoodsById(GameConfig.GAME_ITEM_BUY_PASS_BUFF);
			addition += goodsInfo.getParamList().get(0).longValue() * userPassRoad.getItemBuyBuffTimes();
		}

		addition += CurioMgr.getSkillAdditionBySkillType(eSkillType.PassBattleEarnSkill.getValue(), player, 0);

		//计算加成
		myAbility = new BigDecimal(myAbility).multiply(BigDecimal.valueOf((addition + 1000) / 1000)).setScale(0, BigDecimal.ROUND_UP).toBigInteger();
		if (myAbility.compareTo(enemyAbility) >= 0) {//打得过
			//打赢了,缓存下boss关卡
			UserPassRoad beforePassRoad = new UserPassRoad();
			beforePassRoad.setPassId(userPassRoad.getPassId());
			beforePassRoad.setPassProgress(userPassRoad.getPassProgress());
			beforePassRoad.setTransportId(userPassRoad.getTransportId());
			//关卡ID+1
			throughPassRoad();

			//奖励
			Property reward = new Property(passPointInfo.getReward());
			//击败boss的额外奖励
			reward.addProperty(PropertyHelper.parseStringToProperty(passRoadInfo.getRewards()));

			//获取奖励中的阅历值，马车会增加获得量
			reward = getTransportAdd(reward);

			player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.Pass, eLogMoneyType.PassReward);
			userPassRoad.setBuyBuffTimes(0);
			userPassRoad.setItemBuyBuffTimes(0);
			player.notifyListener(eGamePlayerEventType.PassBattleSuccessTimes.getValue(), 1);
			//平台数据加一下
			player.getModule(XiaoMianModule.class).addPassRoadBossBattleTimes(1);
			if (isBackend) {
				backEndPassRecord.getBossReward().addProperty(reward);
			}
			DataAnalyticsMgr.trackPassRoadBattle(player, true, reward, beforePassRoad, maxSilverBuffTimes, maxItemBuffTimes, true);
		} else {
			// 后台自动贸易谈判失败
			if (isBackend) {
				backEndPassRecord.setStopReason(GameErrorCode.E_PASS_ROAD_BATTLE_ABILITY_NO_ENOUGH);
			}
			DataAnalyticsMgr.trackPassRoadBattle(player, false, new Property(), userPassRoad, maxSilverBuffTimes, maxItemBuffTimes, true);
		}
		return 0;
	}

	//马车加成阅历值
	public Property getTransportAdd(Property oReward){
		Property reward = new Property(oReward);
		//获取奖励中的阅历值，马车会增加获得量
		BigDecimal exp = new BigDecimal(reward.getCountByGoodsId(GameConfig.GAME_MONEY_PATRONS_EXP));
		double expAddition = player.getModule(PassTransportModule.class).getTransportExpAddition();
		//藏宝加成
		expAddition += CurioMgr.getSkillAdditionBySkillType(eSkillType.PassPatronsExpOutputSkill.getValue(), player, 0);

		exp = exp.multiply(BigDecimal.valueOf(expAddition / 1000 + 1)).setScale(0, BigDecimal.ROUND_UP);
		reward.setGood(GameConfig.GAME_MONEY_PATRONS_EXP,exp.toBigInteger());

		//声望
		BigDecimal prestige = new BigDecimal(reward.getCountByGoodsId(GameConfig.GAME_MONEY_PRESTIGE));
		//藏宝加成(固定值)
		double addition = (double) CurioMgr.getSkillAdditionBySkillType(eSkillType.PassPrestigeOutputSkill.getValue(), player, 0);
		prestige = prestige.add(BigDecimal.valueOf(addition));
		reward.setGood(GameConfig.GAME_MONEY_PRESTIGE, prestige.toBigInteger());

		return reward;
	}

	private void throughPassRoad() {
		int nextPassId = userPassRoad.getPassId();
		PassRoadInfo nextPassRoadInfo = PassRoadMgr.getPassRoadInfo(userPassRoad.getPassId() + 1);
		if (null != nextPassRoadInfo) {
			nextPassId = nextPassRoadInfo.getId();
		}else{
			//打到最后一关了没有配置了也加上去的
			nextPassId++;
		}
		userPassRoad.setPassId(nextPassId);
		userPassRoad.setPassProgress(0);
		userPassRoad.setSessionId(1);
		userPassRoad.setModifyTime(System.currentTimeMillis() / 1000);
		player.notifyListener(eGamePlayerEventType.PassBattle.getValue(), userPassRoad);

		notifyPassThrough(userPassRoad);
		player.getModule(PlayerModule.class).checkSystemOpen();

		syncUserPassRoad();
	}

	//修復用户事件因为配置表改表而变成脏数据
	private void repairEvent(){
		for(Integer passId : eventBagMap.keySet()){
			for (Integer sectionId : eventBagMap.get(passId).keySet()){
				UserPassRoadEvent event = eventBagMap.get(passId).get(sectionId);
				PassRoadPointInfo passRoadPointInfo = PassRoadMgr.getPassRoadPointInfo(passId,sectionId);
				if(passRoadPointInfo == null || event.getEventId() != passRoadPointInfo.getEventId()){
					eventBagMap.get(passId).remove(sectionId);
					userPassRoad.setEventData(JSON.toJSONString(eventBagMap));
					userPassRoad.removeUserPassRoadEvent(passId,sectionId,event.getEventId());
				}
			}
		}
		syncUserPassRoad();
	}

	public int passEvent(int passId,int sectionId,int eventId,int selectId,List<Integer> patronIdList,List<Integer> beautyIdList){
		if(!eventBagMap.containsKey(passId)){
			return GameErrorCode.E_PASS_ROAD_EVENT_NOFOUND;
		}
		if(!eventBagMap.get(passId).containsKey(sectionId)){
			return GameErrorCode.E_PASS_ROAD_EVENT_NOFOUND;
		}
		if(eventBagMap.get(passId).get(sectionId).getEventId() != eventId){
			//数据表修改后修改数据
			return GameErrorCode.E_PASS_ROAD_EVENT_NOFOUND;
		}
		PassRoadEventInfo eventInfo = PassRoadMgr.getPassRoadEventInfo(eventId);
		int ret = PassRoadMgr.passEvent(player,eventInfo,selectId,patronIdList,beautyIdList);
		if(ret != 0){
			return ret;
		}
		if (canFinishEventWhenRet0(eventInfo, selectId)) {
			eventBagMap.get(passId).remove(sectionId);
			List<Integer> removeIdList = new ArrayList<>();
			for(int tmpPassId : eventBagMap.keySet()){
				if(eventBagMap.get(tmpPassId).size() == 0){
					removeIdList.add(tmpPassId);
				}
			}
			for(int removeId : removeIdList){
				eventBagMap.remove(removeId);
			}
			userPassRoad.setEventData(JSON.toJSONString(eventBagMap));
			userPassRoad.removeUserPassRoadEvent(passId, sectionId, eventId);
			syncUserPassRoad();
		}
		return 0;
	}

	public String passEventReward(int passId,int sectionId,int eventId,int selectId,List<Integer> patronIdList,List<Integer> beautyIdList){
		if(!eventBagMap.containsKey(passId)){
			return "";
		}
		if(!eventBagMap.get(passId).containsKey(sectionId)){
			return "";
		}
		if(eventBagMap.get(passId).get(sectionId).getEventId() != eventId){
			return "";
		}
		PassRoadEventInfo eventInfo = PassRoadMgr.getPassRoadEventInfo(eventId);
		return PassRoadMgr.passEventReward(player,eventInfo,selectId,patronIdList,beautyIdList);
	}

	/**
	 * 一键处理事件
	 */
	public String oneKeyDealEvent(){
		long nowTime = System.currentTimeMillis();
		Property reward = new Property();
		Map<Integer, List<Integer>> removeMap = new HashMap<>();
		for(Map.Entry<Integer,Map<Integer,UserPassRoadEvent>> dataEntry : eventBagMap.entrySet()){
			for(Map.Entry<Integer,UserPassRoadEvent> eventEntry : dataEntry.getValue().entrySet()){
				PassRoadEventInfo eventInfo = PassRoadMgr.getPassRoadEventInfo(eventEntry.getValue().getEventId());
				if (null != eventInfo
						&& eventInfo.getType() != ePassRoadEventType.DecrepitHouseEvent.getValue()
						&& eventInfo.getType() != ePassRoadEventType.SaveDogEvent.getValue()
						&& eventInfo.getType() != ePassRoadEventType.SmallGameEvent.getValue()) {
					String eventReward = PassRoadMgr.autoDealPassEventReward(player, eventInfo);
					reward.addProperty(PropertyHelper.parseStringToProperty(eventReward));
					UserPassRoadEvent roadEvent = eventEntry.getValue();
					int passId = roadEvent.getPassId();
					int sectionId = roadEvent.getSectionId();
					if (!removeMap.containsKey(passId)) {
						removeMap.put(passId, new ArrayList<>());
					}
					List<Integer> list = removeMap.get(passId);
					list.add(sectionId);
					userPassRoad.removeUserPassRoadEvent(passId, sectionId, roadEvent.getEventId());
				}
			}
		}
		for (Map.Entry<Integer, List<Integer>> entry : removeMap.entrySet()) {
			Integer passId = entry.getKey();
			List<Integer> list = entry.getValue();
			for (Integer sectionId : list) {
				eventBagMap.get(passId).remove(sectionId);
				List<Integer> removeIdList = new ArrayList<>();
				for(int tmpPassId : eventBagMap.keySet()){
					if(eventBagMap.get(tmpPassId).size() == 0){
						removeIdList.add(tmpPassId);
					}
				}
				for(int removeId : removeIdList){
					eventBagMap.remove(removeId);
				}
			}
		}
		userPassRoad.setEventData(JSON.toJSONString(eventBagMap));
		log.info("==========one key deal event use:{} ms", System.currentTimeMillis() - nowTime);

		//加奖励
		player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.PassRoadEvent, eLogMoneyType.EventAutoDealReward);
		//同步事件
		syncUserPassRoad();
		return PropertyHelper.parsePropertyToString(reward);
	}

	/**
	 * 指定关卡挑战
	 * @param passId 关卡id
	 * @param sessionId 小关卡
	 */
	public void jumpToPassRoad(int passId, int sessionId){
		int currPassId = userPassRoad.getPassId();

		//拿boss奖励
		while(passId > currPassId){
			PassRoadInfo passInfo = PassRoadMgr.getPassRoadInfo(currPassId);

			int endProgress;
			List<PassRoadPointInfo>  passRoadPointInfoList = PassRoadMgr.getPassRoadPointList(currPassId);
			endProgress = passRoadPointInfoList.size();

			//获取boss节点
			PassRoadPointInfo passPointInfo = PassRoadMgr.getPassRoadPointInfo(currPassId,endProgress-1);

			Property reward = new Property(passPointInfo.getReward());
			//击败boss的额外奖励
			reward.addProperty(PropertyHelper.parseStringToProperty(passInfo.getRewards()));

			//获取奖励中的阅历值，马车会增加获得量
			reward = getTransportAdd(reward);

			player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.Pass, eLogMoneyType.PassReward);

			UserPassRoad currUserPassRoad = new UserPassRoad();
			currUserPassRoad.setPassId(currPassId);
			currUserPassRoad.setPassProgress(endProgress -1);
			player.notifyListener(eGamePlayerEventType.PassBattle.getValue(), currUserPassRoad);
			notifyPassThrough(currUserPassRoad);

			currPassId++;
		}

		List<PassRoadPointInfo>  passRoadPointInfoList = PassRoadMgr.getPassRoadPointList(passId);
		int progress = 0;
		PassRoadPointInfo pre = null;
		for(PassRoadPointInfo passRoadPointInfo : passRoadPointInfoList){
			if(sessionId == passRoadPointInfo.getSessionId() + 1){
				if(pre == null){
					progress = passRoadPointInfo.getSectionId();
				}else {
					progress = pre.getSectionId();
				}
				userPassRoad.setSessionId(passRoadPointInfo.getSessionId() + 1);
				break;
			}
			pre = passRoadPointInfo;
			userPassRoad.setSessionId(passRoadPointInfo.getSessionId() + 1);
		}

		userPassRoad.setPassId(passId);
		userPassRoad.setPassProgress(progress);
		userPassRoad.setModifyTime(System.currentTimeMillis() / 1000);
		syncUserPassRoad();
	}

	/**
	 * 通过关卡
	 * @param userPassRoad
	 */
	private void notifyPassThrough(UserPassRoad userPassRoad){
		player.notifyListener(eGamePlayerEventType.PassThroughRank.getValue(), userPassRoad);
		//触发现金礼包
		player.notifyListener(eGamePlayerEventType.RechargeThroughPass.getValue(), 0);
		//4.8.1 新服福利活动 关卡通关小活动 如果解锁且有活动则更新大关卡数据
		if (NewServerWelfareMgr.getActivityInfo(eNewServerWelfareActivityType.MissionComplete.getValue()) != null) {
			player.notifyListener(eGamePlayerEventType.NewServerWelfareMission.getValue(), userPassRoad);
		}
	}

	/**
	 * 获取道具鼓舞加成，千分比
	 */
	public int getItemBuffOnceAddition() {
		GoodsInfo goodsInfo = GoodsMgr.getGoodsById(GameConfig.GAME_ITEM_BUY_PASS_BUFF);
		return goodsInfo.getParamList().get(0).intValue();
	}

	/**
	 * 自动买buff，不够谈判就不买
	 */
	private void autoBuyBuff(PassRoadInfo passRoadInfo, int maxSilverBuffTimes, int maxItemBuffTimes,int autoBuffOption) {
		PassRoadPointInfo passPointInfo = PassRoadMgr.getPassRoadPointInfo(userPassRoad.getPassId(), userPassRoad.getPassProgress());
		if (passPointInfo != null && passPointInfo.isBoss()) {
			// 能力值
			BigInteger myAbility = PatronsMgr.getPatronsTotalAbility(player.getUserId());
			BigInteger bossAbility = passPointInfo.getAbility();

			//模拟时，先加藏品
			long curioAdd = CurioMgr.getSkillAdditionBySkillType(eSkillType.PassBattleEarnSkill.getValue(), player, 0);

			// 之前已买次数
			int buyBuffTimes = userPassRoad.getBuyBuffTimes();
			int itemBuyBuffTimes = userPassRoad.getItemBuyBuffTimes();

			// 模拟购买后次数
			int newBuyBuffTimes = buyBuffTimes;
			int newItemBuyBuffTimes = itemBuyBuffTimes;

			// 之前银两
			BigInteger silverCount = player.getModule(PlayerModule.class).getUserInfo().getSilver();
			int bagItemBuffCount = (int) player.getModule(BagModule.class).getUserBagItemCount(GameConfig.GAME_ITEM_BUY_PASS_BUFF);

			// 模拟购买后银两、道具剩余
			BigInteger newSilverCount = silverCount;
			int newBagItemBuffCount = bagItemBuffCount;

			int loopMaxTimes = 1000;
			int loopTimes = 0;

			if(autoBuffOption == 1 || autoBuffOption == 0){
				// 模拟银两买buff
				BigInteger baseSilverCost = new BigInteger(passRoadInfo.getBaseInspireConsume());
				for (loopTimes = 0; loopTimes < loopMaxTimes; loopTimes++) {
					// 当前赚钱是否够了
					int addition = GameConfig.PASS_SILVER_BUFF_ADDITION * newBuyBuffTimes + getItemBuffOnceAddition() * newItemBuyBuffTimes;
					BigInteger newMyAbility = new BigDecimal(myAbility).multiply(new BigDecimal(addition + curioAdd + 1000)).divide(new BigDecimal(1000), 0, BigDecimal.ROUND_UP).toBigInteger();
					if (newMyAbility.compareTo(bossAbility) >= 0) {
						break;
					}
					// 是否超过最大次数
					int nextBuyBuffTimes = newBuyBuffTimes + 1;
					if (nextBuyBuffTimes > ConfigMgr.getMaxPassSilverBuyBuffTimes() || nextBuyBuffTimes > maxSilverBuffTimes + buyBuffTimes) {
						break;
					}
					// 是否还有钱
					BigInteger silverBuyBuffCost = PassRoadMgr.getSilverBuyBuffCost(player, baseSilverCost, newBuyBuffTimes);
					newSilverCount = newSilverCount.subtract(silverBuyBuffCost);
					if (newSilverCount.compareTo(BigInteger.ZERO) < 0) {
						newSilverCount = newSilverCount.add(silverBuyBuffCost);
						break;
					}
					// 模拟鼓舞一次
					newBuyBuffTimes++;
				}
				if (loopTimes >= loopMaxTimes) {
					log.error("[one key backend pass road] loop error on auto buy silver buff!");
					return;
				}

				// 模拟道具买buff
				for (loopTimes = 0; loopTimes < loopMaxTimes; loopTimes++) {
					// 当前赚钱是否够了
					int addition = GameConfig.PASS_SILVER_BUFF_ADDITION * newBuyBuffTimes + getItemBuffOnceAddition() * newItemBuyBuffTimes;
					BigInteger newMyAbility = new BigDecimal(myAbility).multiply(new BigDecimal(addition + curioAdd + 1000)).divide(new BigDecimal(1000), 0, BigDecimal.ROUND_UP).toBigInteger();
					if (newMyAbility.compareTo(bossAbility) >= 0) {
						break;
					}
					// 是否超过最大次数
					int nextItemBuyBuffTimes = newItemBuyBuffTimes + 1;
					if (nextItemBuyBuffTimes > GameConfig.PASS_ITEM_BUY_BUFF_MAX_TIMES || nextItemBuyBuffTimes > maxItemBuffTimes + itemBuyBuffTimes) {
						break;
					}
					// 是否还有道具
					newBagItemBuffCount--;
					if (newBagItemBuffCount < 0) {
						newBagItemBuffCount++;
						break;
					}
					// 模拟鼓舞一次
					newItemBuyBuffTimes++;
				}
				if (loopTimes >= loopMaxTimes) {
					log.error("[one key backend pass road] loop error on auto buy item buff!");
					return;
				}
			}else if(autoBuffOption == 2){
				// 模拟道具买buff
				for (loopTimes = 0; loopTimes < loopMaxTimes; loopTimes++) {
					// 当前赚钱是否够了
					int addition = GameConfig.PASS_SILVER_BUFF_ADDITION * newBuyBuffTimes + getItemBuffOnceAddition() * newItemBuyBuffTimes;
					BigInteger newMyAbility = new BigDecimal(myAbility).multiply(new BigDecimal(addition + curioAdd + 1000)).divide(new BigDecimal(1000), 0, BigDecimal.ROUND_UP).toBigInteger();
					if (newMyAbility.compareTo(bossAbility) >= 0) {
						break;
					}
					// 是否超过最大次数
					int nextItemBuyBuffTimes = newItemBuyBuffTimes + 1;
					if (nextItemBuyBuffTimes > GameConfig.PASS_ITEM_BUY_BUFF_MAX_TIMES || nextItemBuyBuffTimes > maxItemBuffTimes + itemBuyBuffTimes) {
						break;
					}
					// 是否还有道具
					newBagItemBuffCount--;
					if (newBagItemBuffCount < 0) {
						newBagItemBuffCount++;
						break;
					}
					// 模拟鼓舞一次
					newItemBuyBuffTimes++;
				}
				if (loopTimes >= loopMaxTimes) {
					log.error("[one key backend pass road] loop error on auto buy item buff!");
					return;
				}
				// 模拟银两买buff
				BigInteger baseSilverCost = new BigInteger(passRoadInfo.getBaseInspireConsume());
				for (loopTimes = 0; loopTimes < loopMaxTimes; loopTimes++) {
					// 当前赚钱是否够了
					int addition = GameConfig.PASS_SILVER_BUFF_ADDITION * newBuyBuffTimes + getItemBuffOnceAddition() * newItemBuyBuffTimes;
					BigInteger newMyAbility = new BigDecimal(myAbility).multiply(new BigDecimal(addition + curioAdd + 1000)).divide(new BigDecimal(1000), 0, BigDecimal.ROUND_UP).toBigInteger();
					if (newMyAbility.compareTo(bossAbility) >= 0) {
						break;
					}
					// 是否超过最大次数
					int nextBuyBuffTimes = newBuyBuffTimes + 1;
					if (nextBuyBuffTimes > ConfigMgr.getMaxPassSilverBuyBuffTimes() || nextBuyBuffTimes > maxSilverBuffTimes + buyBuffTimes) {
						break;
					}
					// 是否还有钱
					BigInteger silverBuyBuffCost = PassRoadMgr.getSilverBuyBuffCost(player, baseSilverCost, newBuyBuffTimes);
					newSilverCount = newSilverCount.subtract(silverBuyBuffCost);
					if (newSilverCount.compareTo(BigInteger.ZERO) < 0) {
						newSilverCount = newSilverCount.add(silverBuyBuffCost);
						break;
					}
					// 模拟鼓舞一次
					newBuyBuffTimes++;
				}
				if (loopTimes >= loopMaxTimes) {
					log.error("[one key backend pass road] loop error on auto buy silver buff!");
					return;
				}
			}else{
				log.error("[one key backend pass road] loop error on auto buy silver buff option err!");
				return;
			}

			// 当前赚钱是否够了
			int addition = GameConfig.PASS_SILVER_BUFF_ADDITION * newBuyBuffTimes + getItemBuffOnceAddition() * newItemBuyBuffTimes;
			BigInteger newMyAbility = new BigDecimal(myAbility).multiply(new BigDecimal(addition + curioAdd + 1000)).divide(new BigDecimal(1000), 0, BigDecimal.ROUND_UP).toBigInteger();
			if (newMyAbility.compareTo(bossAbility) >= 0) {
				// 真正买buff
				buyBuff(1, newBuyBuffTimes - buyBuffTimes);
				buyBuff(2, newItemBuyBuffTimes - itemBuyBuffTimes);
				// 记录
				backEndPassRecord.getCost().addProperty(GameConfig.GAME_MONEY_SILVER, silverCount.subtract(newSilverCount));
				backEndPassRecord.getCost().addProperty(GameConfig.GAME_ITEM_BUY_PASS_BUFF, BigInteger.valueOf(bagItemBuffCount - newBagItemBuffCount));
				backEndPassRecord.setAutoBuyBuffTimes(newBuyBuffTimes - buyBuffTimes);
				backEndPassRecord.setAutoItemBuyBuffTimes(newItemBuyBuffTimes - itemBuyBuffTimes);
			}
		}
	}

	/**
	 * 获取后台自动贸易详情msg
	 */
	public RoadProto.PassRoadBackendDetailRespMsg.Builder getPassRoadBackendDetailRespMsg() {
		return PassRoadPb.parsePassRoadBackendDetailRespMsg(backEndPassRecord);
	}

	/**
	 * 重置后台自动贸易数据
	 */
	public void resetBackEndPassRecord() {
		backEndPassRecord.reset();
	}

	/**
	 * 设置后台自动贸易结束关卡
	 */
	public void setBackEndEndPass() {
		backEndPassRecord.setEndPassId(userPassRoad.getPassId());
        PassRoadPointInfo pointInfo = PassRoadMgr.getPassRoadPointInfo(userPassRoad.getPassId(), userPassRoad.getPassProgress());
		if (pointInfo != null) {
			backEndPassRecord.setEndSessionId(pointInfo.getSessionId());
		} else {
			log.info("set BackEndPassRecord.endSessionId error! PassRoadMgr.getPassRoadPointInfo(passId = {}, passProgress = {})", userPassRoad.getPassId(), userPassRoad.getPassProgress());
		}
	}

	/**
	 * 获取后台自动贸易自动买buff次数
	 */
	public Map<Integer, Integer> getAndResetAutoBuyBuffTimes() {
		Map<Integer, Integer> result = new HashMap<>();
		result.put(1, backEndPassRecord.getAutoBuyBuffTimes());
		result.put(2, backEndPassRecord.getAutoItemBuyBuffTimes());
		backEndPassRecord.setAutoBuyBuffTimes(0);
		backEndPassRecord.setAutoItemBuyBuffTimes(0);
		return result;
	}

	/**
	 * 设置停止后台自动原因
	 */
	public void setBackEndStopReason(int stopReason) {
		if (stopReason != 0) {
			backEndPassRecord.setStopReason(stopReason);
		}
	}

	/**
	 * 能否完成事件
	 * （有些事件ret=0但是不能完成）
	 */
	public boolean canFinishEventWhenRet0(PassRoadEventInfo eventInfo, int selectId) {
		// 拯救狗狗事件
		if (eventInfo.getType() == ePassRoadEventType.SaveDogEvent.getValue()) {
			if (selectId != 1) {
				return false;
			}
		}

		// 默认可以完成
		return true;
	}

}
